package com.mj.mes.messagesHandler;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.mj.factory.kanBan.KanBanController;
import com.mj.factory.workOrder.WorkOrder;
import com.mj.factory.workOrder.WorkOrderService;
import com.mj.factory.workOrder.WorkOrderStatus;
import com.mj.mes.messages.MachineStatusChange;
import com.mj.mes.messages.Messages;
import com.mj.mes.messages.WorkFinished;
import com.mj.mes.messages.WorkStarted;
import com.mj.mes.system.SysMechanics.SysMechanics;
import com.mj.mes.system.SysMechanics.SysMechanicsService;
import com.mj.processController.ProcessEngineCore;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.hibernate.SQLQuery;
import org.hibernate.transform.Transformers;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import java.util.List;
import java.util.Map;
import java.util.Random;

/**
 * author : cRyann
 *
 * @create 2017-10-11
 **/
@Controller
public class SimulatorHandler {

    private Logger logger = Logger.getLogger(this.getClass());

    @Autowired
    private SysMechanicsService sysMechanicsService;
    @Autowired
    private WorkOrderService workOrderService;
    @Autowired
    ProcessEngineCore processEngineCore;
    @Autowired
    KanBanController kanBanController;

    @Autowired
    @PersistenceContext
    private EntityManager em;

    /**
    *@author cRyann
    *@param
    *@Description 接受RabbitMQ的信息，并处理
    **/
    @RabbitListener(queues = "DEVICE_SIMULATOR_QUEUE", containerFactory = "rabbitListenerContainerFactory")
    public void process(Messages<Object> object) throws Exception {
        ObjectMapper objectMapper = new ObjectMapper();
        String json = objectMapper.writeValueAsString(object);
//        logger.info(json);
        String bodyJson = objectMapper.readTree(json).get("body").toString();
        String nodeBody = objectMapper.readTree(bodyJson).toString();

        String handlerName = object.getMessageName();
        logger.info("Rec:[" + handlerName + "]");

        switch (handlerName) {
            case "MachineStatusChange":
                MachineStatusChange msc = objectMapper.readValue(nodeBody, MachineStatusChange.class);
                SysMechanics sysMechanics = sysMechanicsService.findByDevicePosition(msc.getMachineName());
                sysMechanics.setDeviceState(Integer.parseInt(msc.getCurrentStatus()));
                sysMechanicsService.updateMechanics(sysMechanics);
                kanBanController.sendDeviceColor(sysMechanics);
                break;
            case "WorkStarted":
                WorkStarted ws = objectMapper.readValue(nodeBody, WorkStarted.class);
                // ProcessEngineCore do something
                processEngineCore.workStartByProcessDefinitionId(ws.getChartNumber(), null);
                kanBanController.sendWorkOrderData();
                kanBanController.sendChartsData(null);
                break;
            case "WorkFinished":
                WorkFinished wf = objectMapper.readValue(nodeBody, WorkFinished.class);
                // ProcessEngineCore do something
                String technologyName = processEngineCore.workCompleteByProcessDefinitionId(wf.getChartNumber(), null);
                kanBanController.sendWorkOrderData();
                kanBanController.sendChartsData(technologyName);
                if (processEngineCore.isProcessEndByProcessDefinitionId(wf.getChartNumber())) {
                    String chartNumber = StringUtils.substringBetween(wf.getChartNumber(), "Process_", ":");
                    WorkOrder workOrder = workOrderService.findByChartNumber(chartNumber);
                    if (null != workOrder) {
                        workOrder.setWorkOrderStatus(WorkOrderStatus.StatusEnum.Completed.toString());
                        workOrderService.save(workOrder);
                    }
                }
//                randomDeployProcess();
                break;
            default:
                return;
        }
    }

    public void randomDeployProcess() {
        Random random = new Random();
        String sql = "SELECT pro.KEY_ as procdefKey "
                + "FROM act_re_procdef pro  "
                + "WHERE pro.ID_ NOT IN ( SELECT exe.PROC_DEF_ID_ FROM act_ru_execution exe)";
        Query query = em.createNativeQuery(sql);
        query.unwrap(SQLQuery.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
        List list = query.getResultList();
        if (list.size() > 3) {
            int r = random.nextInt(list.size());
            Map map = (Map) list.get(r);
            processEngineCore.startInstanceByKey((String) map.get("procdefKey"), null);
        }
    }
}
